from fastapi import FastAPI, HTTPException, Body, Query, UploadFile, File, Form
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, StreamingResponse
from langchain_openai import OpenAIEmbeddings
from pydantic import BaseModel
from motor.motor_asyncio import AsyncIOMotorClient
from bson import ObjectId
from datetime import datetime
import bcrypt
import os
import pathlib
import shutil
import json
from typing import Optional, List


from ai_chat import ask_agent, ask_knowledge_base,ask_agent_stream
from outputParser import create_wall_output_parser
from get_news import fetch_news,get_BIM_news
from pathlib import Path
from createVectorDB import CreateDatabase_character_split, CreateDatabase_title_split,CreateDatabase_markdown_split, delete_vector_db_by_ids,load_vector_store,delete_vector_database,close_all_qdrant_clients,create_vector_store_collection
import urllib.parse

from fastapi.responses import JSONResponse
from parser_ocr import qwen_parser,qwen_parser_multi,slicon_qwen_parser
import atexit
# api_key="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"
# api_key="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"
# base_url="https://api.openai.com/v1"
api_key="sk-edsqqcdsyjftrvxhxmhorylyieeeqrrwfujubikaxpvphqsq"
from siliconflow_embeddings import SiliconFlowEmbeddings

embeddings = SiliconFlowEmbeddings(
        api_key=api_key,
        model="BAAI/bge-m3" # 默认值
    )
app = FastAPI()
# 注册退出时的清理函数
atexit.register(close_all_qdrant_clients)
# CORS配置
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# MongoDB配置
MONGO_URL = "mongodb://localhost:27017"
DATABASE_NAME = "chat_database"
client = AsyncIOMotorClient(MONGO_URL)
db = client[DATABASE_NAME]
users_collection = db["users"]

# Pydantic模型
class UserRegister(BaseModel):
    username: str
    password: str

class UserLogin(BaseModel):
    username: str
    password: str

class ChangePassword(BaseModel):
    username: str
    old_password: str
    new_password: str

class ChatCreate(BaseModel):
    user_id: str
    title: str
    scene: Optional[str] = "chat"

class MessageSend(BaseModel):
    user_id: str
    chat_id: str
    user_message: str
    ai_message: str
    usertimestamp: Optional[int] = None
    aitimestamp: Optional[int] = None
    vote: Optional[int] = 0


def encode_path_to_utf8(path):
    """将路径中的中文部分转为 UTF-8 编码"""
    return urllib.parse.quote(path)

def decode_path_from_utf8(encoded_path):
    """将 UTF-8 编码的路径解码回中文"""
    return urllib.parse.unquote(encoded_path)

# 工具函数
async def get_user(user_id: str):
    user = await users_collection.find_one({"_id": ObjectId(user_id)})
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return user

# 根路由
@app.get("/")
async def root():
    return {
        "status": "success",
        "message": "FastAPI server is running",
        "version": "1.0"
    }

# 用户注册
@app.post("/api/register")
async def register(user: UserRegister):
    existing_user = await users_collection.find_one({"username": user.username})
    if existing_user:
        raise HTTPException(status_code=400, detail="用户名已存在")
    if(user.username == "" or user.password == ""):
        raise HTTPException(status_code=400, detail="用户名或密码不能为空")
    hashed_password = bcrypt.hashpw(user.password.encode(), bcrypt.gensalt())
    result = await users_collection.insert_one({
        "username": user.username,
        "password": hashed_password.decode(),
        "chats": [],
        "files": [],
        "userIcon": "default.png"
    })
    return {"message": "Registration successful", "user_id": str(result.inserted_id)}

# 用户登录
@app.post("/api/login")
async def login(user: UserLogin):
    db_user = await users_collection.find_one({"username": user.username})
    if not db_user or not bcrypt.checkpw(user.password.encode(), db_user["password"].encode()):
        raise HTTPException(status_code=401, detail="用户名或密码错误")
    if user.username == "" or user.password == "":
        raise HTTPException(status_code=400, detail="用户名或密码不能为空")
    return {"message": "登陆成功！", "user_id": str(db_user["_id"])}

# 修改密码
@app.post("/api/change_password")
async def change_password(request: ChangePassword):
    user = await users_collection.find_one({"username": request.username})
    if not user:
        raise HTTPException(status_code=404, detail="用户未找到")
    if not bcrypt.checkpw(request.old_password.encode(), user["password"].encode()):
        raise HTTPException(status_code=401, detail="旧密码错误")
    new_password = bcrypt.hashpw(request.new_password.encode(), bcrypt.gensalt()).decode()
    if(request.new_password == "" or request.old_password == ""):
        raise HTTPException(status_code=400, detail="新密码或旧密码不能为空")
    await users_collection.update_one(
        {"username": request.username},
        {"$set": {"password": new_password}}
    )
    return {"message": "密码修改成功"}


# 获取聊天列表
@app.get("/api/chat_list")
async def get_chat_list(user_id: str = Query(...)):
    user = await get_user(user_id)
    chats = sorted(user.get("chats", []), 
                  key=lambda x: x["created_at"], 
                  reverse=True)
    return {"chats": [{
        "id": str(chat["_id"]),
        "title": chat["title"],
        "created_at": chat["created_at"]
    } for chat in chats]}

#更改聊天标题
# 请求体模型
class UpdateChatTitleRequest(BaseModel):
    user_id: str
    chat_id: str
    new_title: str

@app.post("/api/update_chat_title")
async def update_chat_title(request: UpdateChatTitleRequest):
    user = await db.users.find_one({"_id": ObjectId(request.user_id)})
    if not user:
        raise HTTPException(status_code=404, detail="用户未找到")

    chats = user.get("chats", [])
    for chat in chats:
        if str(chat["_id"]) == request.chat_id:
            chat["title"] = request.new_title
            await db.users.update_one(
                {"_id": ObjectId(request.user_id)},
                {"$set": {"chats": chats}}
            )
            return {"message": "聊天标题更新成功"}

    raise HTTPException(status_code=404, detail="聊天未找到")
#获取聊天记录
@app.get("/api/chat_messages")
async def get_chat_messages(chat_id: str = Query(...), user_id: str = Query(...)):
    if not ObjectId.is_valid(user_id) or not ObjectId.is_valid(chat_id):
        raise HTTPException(status_code=400, detail="聊天ID或者用户ID无效")
    
    user = await db["users"].find_one({"_id": ObjectId(user_id)})
    if not user:
        raise HTTPException(status_code=404, detail="用户未找到")
    
    chat = next((chat for chat in user.get("chats", []) if str(chat.get("_id")) == chat_id), None)
    if not chat:
        raise HTTPException(status_code=404, detail="聊天未找到")
    return {"messages": chat.get("messages", []),"scene": chat.get("scene")}

# 创建聊天
@app.post("/api/create_chat")
async def create_chat(chat: ChatCreate):
    new_chat = {
        "_id": ObjectId(),
        "title": chat.title,
        "scene": chat.scene,
        "messages": [],
        "created_at": datetime.now()
    }
    result = await users_collection.update_one(
        {"_id": ObjectId(chat.user_id)},
        {"$push": {"chats": new_chat}}
    )
    if result.modified_count == 0:
        raise HTTPException(status_code=400, detail="Failed to create chat")
    return {"message": "聊天创建成功", "chat_id": str(new_chat["_id"])}

#删除聊天
# 请求体模型
class DeleteChatRequest(BaseModel):
    user_id: str
    chat_id: str

@app.post("/api/delete_chat")
async def delete_chat(request: DeleteChatRequest):
    user = await db.users.find_one({"_id": ObjectId(request.user_id)})
    if not user:
        raise HTTPException(status_code=404, detail="用户未找到")

    chats = user.get("chats", [])
    chat_exists = any(str(chat["_id"]) == request.chat_id for chat in chats)
    
    if not chat_exists:
        raise HTTPException(status_code=404, detail="聊天未找到")

    # 删除聊天记录
    result = await db.users.update_one(
        {"_id": ObjectId(request.user_id)},
        {"$pull": {"chats": {"_id": ObjectId(request.chat_id)}}}
    )

    if result.modified_count > 0:
        return {"message": "聊天记录删除成功"}
    else:
        raise HTTPException(status_code=400, detail="聊天记录删除失败")

# 发送消息
@app.post("/api/send_message")
async def send_message(message: MessageSend):
    user = await get_user(message.user_id)
    print('发送用户消息:'+message.user_message)
    
    # 生成时间戳
    usertimestamp = message.usertimestamp or int(datetime.now().timestamp()*1000)
    aitimestamp = message.aitimestamp or usertimestamp + 10
    
    # 更新消息
    update_result = await users_collection.update_one(
        {"_id": ObjectId(message.user_id), "chats._id": ObjectId(message.chat_id)},
        {"$push": {
            "chats.$.messages": {
                "sender": "user",
                "content": message.user_message,
                "timestamp": usertimestamp
            }
        }
        }
    )
    update_result = await users_collection.update_one(
        {"_id": ObjectId(message.user_id), "chats._id": ObjectId(message.chat_id)},
        {
        "$push":{
            "chats.$.messages": {
                "sender": "ai",
                "content": message.ai_message,
                "timestamp": aitimestamp,
                "vote": message.vote
            }
        }
        }
    )
    
    if update_result.modified_count == 0:
        raise HTTPException(status_code=400, detail="Failed to send message")
    
    return {"message": "Message sent successfully"}
#获取AI回复
# 请求体模型
class Message(BaseModel):
    sender: str
    content: str
    timestamp: Optional[int] = None

class AgentRequest(BaseModel):
    message: str
    chat_history: Optional[List[Message]] = []
    user_id: Optional[str] = None
    ifUseKnowldgeBase: Optional[bool] = True
    ifUseWeb: Optional[bool] = True
    systemPrompt: Optional[str] = None
@app.post("/api/get_agent_response")

async def get_agent_response(request: AgentRequest):
    if not request.message:
        raise HTTPException(status_code=400, detail="Message is required")
    try:
        response =await ask_agent(request.message, request.chat_history, request.user_id,request.ifUseKnowldgeBase,request.ifUseWeb,embeddings)    
        return {"response": response}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error processing request: {str(e)}")

# 获取Agent流式回复
@app.post("/api/get_agent_response_stream")
async def get_agent_response_stream(request: AgentRequest):
    if not request.message:
        raise HTTPException(status_code=400, detail="Message is required")
    try:
        response =await ask_agent_stream(request.message, request.chat_history, request.user_id,request.ifUseKnowldgeBase,request.ifUseWeb,request.systemPrompt,embeddings)
        async def streaming(response):
            async for message_chunk,metadata in response:
                content=message_chunk.content
                if content and metadata:
                    if metadata.get("langgraph_node")=='chatbot':
                        # print(content,flush=True)
                        yield content
                # if metadata:
                #     print(metadata,flush=True)
        return StreamingResponse(streaming(response), media_type="text/plain") 
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error processing request: {str(e)}")

# 创建知识库文件夹
@app.post("/api/create_kbfolder")
async def create_kbfolder(user_id: str = Body(...), folder_name: str = Body(...)):
    folder_path = pathlib.Path(f"{user_id}/{folder_name}")
    vector_db_path = pathlib.Path(f"{user_id}/vector_db")
    try:
        folder_path.mkdir(parents=True, exist_ok=True)
        vector_db_path.mkdir(parents=True, exist_ok=True)
        create_vector_store_collection(vector_db_path,folder_name)  # 创建向量库集合
        return {"message": "文件夹创建成功"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/api/get_kbfolders")
#获取文件夹列表
async def get_kbfolders(user_id: str = Query(...)):
    folder_path = pathlib.Path(user_id)
    if not folder_path.exists():
        return []
    
    subfolders = []
    for entry in folder_path.iterdir():
        if entry.is_dir():
            if entry.name!= "vector_db":  # 排除向量库文件夹
                subfolders.append({
                    "name": entry.name,
                    "creationTime": entry.stat().st_ctime,
                    "fileCount": len(list(entry.glob("*")))
                })
    print("文件夹列表", subfolders)
    return subfolders

# 删除文件夹
class DeleteFolderRequest(BaseModel):
    user_id: str
    folder_name: str

@app.post("/api/delete_kbfolder")
async def delete_kbfolder(request: DeleteFolderRequest):
    print("删除文件夹", request)
    folder_path = f"./{request.user_id}/{request.folder_name}"
    vector_db_path = f"./{request.user_id}/vector_db"

    try:
        # 使用shutil.rmtree递归删除文件夹
        shutil.rmtree(folder_path)
        # 删除向量数据库
        delete_vector_database(vector_db_path, request.folder_name)
        
        return {"message": "文件夹删除成功"}
    except Exception as err:
        print("文件夹删除失败", err)
        raise HTTPException(status_code=500, detail="服务器错误")


# 重命名知识库文件夹
class RenameFolderRequest(BaseModel):
    user_id: str
    old_folder_name: str
    new_folder_name: str

@app.post("/api/rename_kbfolder")
async def rename_kbfolder(request: RenameFolderRequest):
    print("修改文件夹名称", request)
    old_folder_path = f"./{request.user_id}/{request.old_folder_name}"
    new_folder_path = f"./{request.user_id}/{request.new_folder_name}"

    try:
        # 使用os.rename重命名文件夹
        os.rename(old_folder_path, new_folder_path)
        return {"message": "文件夹名称修改成功"}
    except Exception as err:
        print("文件夹名称修改失败", err)
        raise HTTPException(status_code=500, detail="服务器错误")

# 定义请求体的数据结构，用于写入配置文件
class WriteConfigRequest(BaseModel):
    user_id: str
    folder_name: str
    config: dict

@app.post("/api/write_kbconfig")
async def write_kbconfig(request: WriteConfigRequest):
    print("写入配置文件", request)
    file_path = f"./{request.user_id}/{request.folder_name}/config.json"

    try:
        # 写入配置文件
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump(request.config, f, ensure_ascii=False, indent=2)
        return {"message": "配置文件写入成功"}
    except Exception as err:
        print("配置文件写入失败", err)
        raise HTTPException(status_code=500, detail="服务器错误")

# 读取配置文件
@app.get("/api/read_kbconfig")
async def read_kbconfig(user_id: str = Query(...), folder_name: str = Query(...)):
    print("读取配置文件", {"user_id": user_id, "folder_name": folder_name})
    file_path = f"./{user_id}/{folder_name}/config.json"
    try:
        # 读取配置文件
        with open(file_path, 'r', encoding='utf-8') as f:
            config = json.load(f)
        return {"config": config}
    except Exception as err:
        print("配置文件读取失败", err)
        raise HTTPException(status_code=500, detail="服务器错误")

#上传知识库文件
BASE_DIR = Path(".")

@app.post("/api/upload_kbfile")
async def upload_kbfile(
    user_id: str = Form(...), folder_name: str = Form(...), file: UploadFile = File(...)
):
    if file.content_type != "application/pdf" and file.content_type != "text/plain": 
        raise HTTPException(status_code=400, detail="只能上传 PDF、txt文件")
    # file_name=encode_path_to_utf8(file_name) #utf8编码
    file_name = file.filename.split('.')[0]  # 获取文件名，不包含扩展名
    dir_path = BASE_DIR / user_id / folder_name/file_name
    dir_path.mkdir(parents=True, exist_ok=True)
    file_path = dir_path / "rawData"
    with file_path.open("wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
    return {"message": "文件上传成功", "file_name": file.filename}

#删除知识库文件
@app.post("/api/delete_kbfile")
async def delete_kbfile(user_id: str = Body(...), folder_name: str = Body(...), file_name: str = Body(...)):
    path = BASE_DIR / user_id / folder_name / file_name
    fileconfig_path = BASE_DIR / user_id / folder_name / file_name / "fileconfig.json"
    if fileconfig_path.exists():
        with fileconfig_path.open("r", encoding="utf-8") as f:
            fileconfig = json.load(f)
            uuids= fileconfig.get("uuids", [])
            if uuids.__len__() > 0:
                # 删除向量数据库
                vector_db_path = BASE_DIR / user_id / "vector_db" 
                delete_vector_db_by_ids(vector_db_path, folder_name, uuids,embeddings)
    if path.exists():
        shutil.rmtree(path, ignore_errors=True)
        return {"message": "文件删除成功"}
    raise HTTPException(status_code=404, detail="文件或文件夹不存在")

#重命名知识库文件
@app.post("/api/rename_kbfile")
async def rename_kbfile(user_id: str = Body(...), folder_name: str = Body(...), old_file_name: str = Body(...), new_file_name: str = Body(...)):
    old_file_name_kbfile=old_file_name
    new_file_name_kbfile=new_file_name
    old_path = BASE_DIR / user_id / folder_name /  old_file_name
    old_path2 = BASE_DIR / user_id / folder_name / old_file_name_kbfile
    new_path = BASE_DIR / user_id / folder_name / new_file_name_kbfile
    if old_path.exists():
        old_path.rename(new_path)
        return {"message": "文件名称修改成功"}
    if old_path2.exists():
        old_path2.rename(new_path)
        return {"message": "文件名称修改成功"}
    raise HTTPException(status_code=404, detail="文件不存在")

#获取知识库文件列表
@app.get("/api/get_kbfiles")
async def get_kbfiles(user_id: str = Query(...), folder_name: str = Query(...)):
    folder_path = BASE_DIR / user_id / folder_name
    if not folder_path.exists():
        raise HTTPException(status_code=404, detail="文件夹不存在")
    
    subfolders = []
    for item in folder_path.iterdir():
        if item.is_dir():
            config_path = item / "fileconfig.json"
            config = {}
            if config_path.exists():
                try:
                    with config_path.open("r", encoding="utf-8") as f:
                        config = json.load(f)
                except json.JSONDecodeError:
                    raise HTTPException(status_code=500, detail="配置文件解析失败")
            subfolders.append({"name": item.name, "creationTime": item.stat().st_ctime, "config": config})
    return subfolders

#写入知识库文件配置
@app.post("/api/write_kbfileconfig")
async def write_kbfileconfig(user_id: str = Body(...), folder_name: str = Body(...), file_name: str = Body(...), config: dict = Body(...)):
    file_name=file_name.split('.')[0]
    # file_name=encode_path_to_utf8(file_name) #utf8编码
    file_name=file_name
    file_path = BASE_DIR / user_id / folder_name / file_name / "fileconfig.json"
    file_path.parent.mkdir(parents=True, exist_ok=True)
    with file_path.open("w", encoding="utf-8") as f:
        json.dump(config, f, ensure_ascii=False, indent=2)
    return {"message": "配置文件写入成功"}

#读取知识库文件配置
@app.get("/api/read_kbfileconfig")
async def read_kbfileconfig(user_id: str = Query(...), folder_name: str = Query(...), file_name: str = Query(...)):
    # file_name=encode_path_to_utf8(file_name) #utf8编码
    file_name=file_name
    file_path = BASE_DIR / user_id / folder_name / file_name / "fileconfig.json"
    if file_path.exists():
        with file_path.open("r", encoding="utf-8") as f:
            config = json.load(f)
        return {"config": config}
    raise HTTPException(status_code=404, detail="配置文件不存在")
    
#获取Revit创建墙的结构化输出
class UserRequest(BaseModel):
    message: str
@app.post("/api/create_wall")
async def get_wall_info(request: UserRequest):
    print("获取墙的信息",request.message)
    try:
        wall_info = create_wall_output_parser(request.message)
        return {"response": wall_info}
    except Exception as err:
        print("获取墙的信息失败", err)
        raise HTTPException(status_code=500, detail="服务器错误")
# 获取新闻信息
@app.get("/api/get_ai_news")
async def get_news(pastdays: int = Query(...)):
    print("获取新闻信息")
    urls = [
        'https://ai-bot.cn/daily-ai-news/'
    ]
    try:
        news_list = fetch_news(urls, pastdays)
        return {"news": [news for news in news_list]}
    except Exception as err:
        print("获取新闻信息失败", err)
        raise HTTPException(status_code=500, detail="服务器错误")

#获取BIM新闻消息
@app.get("/api/get_bim_news")
async def get_bim_news(query: str = Query(...)):
    print("问题"+query)
    try:
        response = get_BIM_news(query)
        return {"response": response}
    except Exception as err:
        print("获取BIM新闻信息失败", err)
        raise HTTPException(status_code=500, detail="服务器错误")


# 下载知识库文件
@app.get("/api/download_kbfile")
async def download_kbfile(user_id: str = Query(...), folder_name: str = Query(...), file_name: str = Query(...)):
    file_path = BASE_DIR / user_id / folder_name / file_name / "rawData"
    file_name_kbfile=file_name
    file_path2 = BASE_DIR / user_id / folder_name / file_name_kbfile / "rawData"
    if not file_path.exists() and not file_path2.exists():
        raise HTTPException(status_code=404, detail="文件不存在")
    if file_path.exists():
        return FileResponse(str(file_path), filename="下载文件.pdf")
    else:
        return FileResponse(str(file_path2), filename="下载文件.pdf")

# 下载分块文件
@app.get("/api/download_chunkfile")
async def download_chunkfile(user_id: str = Query(...), folder_name: str = Query(...), file_name: str = Query(...)):
    chunk_path = BASE_DIR / user_id / folder_name / file_name / "chunk.txt"
    file_name_kbfile=file_name
    chunk_path2 = BASE_DIR / user_id / folder_name / file_name_kbfile / "chunk.txt"
    if not chunk_path.exists() and not chunk_path2.exists():
        raise HTTPException(status_code=404, detail="分块文件不存在")
    if chunk_path.exists():
        return FileResponse(str(chunk_path), filename="chunk.txt")
    if chunk_path2.exists():
        return FileResponse(str(chunk_path2), filename="chunk.txt")
#创建向量库
@app.post("/api/create_vector_db")
async def create_vector_db(user_id: str = Body(...), folder_name: str = Body(...), file_name: str = Body(...), config: dict = Body(...),file_type: str = Body(...)):
    
    try:
        # file_name=encode_path_to_utf8(file_name) #utf8编码
        filepath = BASE_DIR / user_id / folder_name / file_name / "rawData"
        savepath = BASE_DIR / user_id / folder_name / file_name 
        vector_db_path = BASE_DIR / user_id / "vector_db" 
        # 确保向量库目录存在
        vector_db_path.mkdir(parents=True, exist_ok=True)
        # 确保 savepath 目录存在
        savepath.mkdir(parents=True, exist_ok=True)
        # 使用 os.path.join 确保路径处理正确
        # 设置当前工作目录为 savepath
        if config["ifMarkdown"] == "true":
            uuids=await CreateDatabase_markdown_split(str(vector_db_path),folder_name,embeddings,str(filepath), str(savepath),file_type ,int(config["splitToken"]), int(config["overlap"]),config["ifOCR"])         
        elif config["titleSeparator"] == "h0":
            uuids=await CreateDatabase_character_split(str(vector_db_path),folder_name,embeddings,str(filepath), str(savepath), file_type, config["segmentIdentifier"], int(config["splitToken"]), int(config["overlap"]),config["ifOCR"]) 
        else:
            uuids=await CreateDatabase_title_split(str(vector_db_path),folder_name,embeddings,str(filepath), str(savepath), file_type, config["titleSeparator"],config["ifOCR"])
        # 写入配置文件
        config_file_path = BASE_DIR / user_id / folder_name / file_name / "fileconfig.json"
        if config_file_path.exists():
            with config_file_path.open("r", encoding="utf-8") as f:
                config = json.load(f)
                if uuids.__len__() > 0:
                    config["uuids"].extend(uuids)
                    config["ifVectorDB"]=1
                else:
                    config["ifVectorDB"]=-1
                    return {"message": "向量库创建失败，未生成向量数据"}
                await write_kbfileconfig(user_id, folder_name, file_name, config)
        return {"message": "向量库创建成功","uuids": uuids, "collection_name": folder_name}
    except Exception as err:
        print("向量库创建失败", err)
        # 写入配置文件
        config_file_path = BASE_DIR / user_id / folder_name / file_name / "fileconfig.json"
        if config_file_path.exists():
            with config_file_path.open("r", encoding="utf-8") as f:
                config = json.load(f)
                config["ifVectorDB"]=-1
                await write_kbfileconfig(user_id, folder_name, file_name, config)
        raise HTTPException(status_code=500, detail="服务器错误")
#对向量库进行知识检索
@app.post("/api/ask_vector_db")
async def ask_vector_db(user_id: str = Body(...), folder_name: str = Body(...), message: str = Body(...)):
    # embeddings = OpenAIEmbeddings(
    #     api_key=api_key,
    #     base_url=base_url
    # )
    # embeddings = embeddings
    collection_name = folder_name
    try:
        filepath = BASE_DIR / user_id / folder_name
        vector_db_path = BASE_DIR / user_id / "vector_db"
        config_file = filepath / "config.json"
        if config_file.exists(): #如果知识库文件夹下有config.json文件
            with open(config_file, "r", encoding='utf-8') as file:
                config = json.load(file)
                collection_name = config["collection_name"]
        vector_db = load_vector_store(str(vector_db_path), collection_name, embeddings)
        response = await ask_knowledge_base(message, vector_db)
        return {"response": response}
    except Exception as err:
        print("向量库检索失败", err)
        raise HTTPException(status_code=500, detail="服务器错误")
#将图片转换成markdown格式
@app.post("/api/analyze-image")
async def analyze_image(file: UploadFile = File(...)):
    # 检查是否提供了文件
    if not file:
        raise HTTPException(status_code=400, detail="No image provided")
    try:       
        # markdown =await qwen_parser(file)
        markdown=await slicon_qwen_parser(file)
        # print(markdown)

        return JSONResponse(content={
            "success": True,
            "markdown": markdown
        })

    except Exception as e:
        return JSONResponse(content={
            "success": False,
            "error": str(e)
        }, status_code=500)
    
#将图片转换成markdown格式
@app.post("/api/analyze-image-multi")
async def analyze_image_multi(file: UploadFile = File(...),page: str = Form(...)):
    # 检查是否提供了文件
    if not file:
        raise HTTPException(status_code=400, detail="No image provided")
    try:       
        markdown =await qwen_parser_multi(file,page)
        # print(markdown)

        return JSONResponse(content={
            "success": True,
            "markdown": markdown
        })

    except Exception as e:
        return JSONResponse(content={
            "success": False,
            "error": str(e)
        }, status_code=500)

# 其他路由的实现方式类似，以下是启动代码
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=3000)